This example is for the EXCLUSION constraint in Postgresql. I will do an example with overlapping date ranges. The table in SQL can be created by $(D $(D sql CREATE TABLE b ( id INTEGER NOT NULL PRIMARY KEY, p PERIOD ); ALTER TABLE b ADD EXCLUDE USING gist (p WITH &&); ))
1 import std.datetime; 2 3 import db_constraints; 4 5 struct Period 6 { 7 Date startDate; 8 Date endDate; 9 10 invariant 11 { 12 assert(startDate <= endDate); 13 } 14 15 bool overlapsWith(in Period i) 16 { 17 return (this.startDate <= i.endDate && i.startDate <= this.endDate); 18 } 19 } 20 21 @ExclusionConstraint!((a, b) => a.p.overlapsWith(b.p)) 22 class B 23 { 24 private int _id; 25 // marking id with not null and primary key 26 @NotNull @PrimaryKeyColumn 27 @property int id() 28 { 29 return _id; 30 } 31 @property void id(int value) 32 { 33 setter(_id, value); 34 } 35 36 private Period _p; 37 @property inout(Period) p() inout 38 { 39 return _p; 40 } 41 @property void p(Period value) 42 { 43 setter(_p, value); 44 } 45 46 this(int id_, Period p_) 47 { 48 this._id = id_; 49 this._p = p_; 50 // do not forget to initialize the keyed item! 51 initializeKeyedItem(); 52 } 53 54 // do not forget to add in the keyed item! 55 mixin KeyedItem!(); 56 } 57 58 alias Bs = BaseKeyedCollection!(B); 59 60 import std.exception : assertNotThrown, assertThrown; 61 62 auto bs = new Bs(); 63 64 auto first = Period(Date(2009, 01, 05), Date(2009, 01, 10)); 65 assertNotThrown!ExclusionConstraintException(bs.add(new B(1, first))); 66 auto second = Period(Date(2009, 01, 07), Date(2009, 01, 12)); 67 assert(first.overlapsWith(second)); 68 assertThrown!ExclusionConstraintException(bs.add(new B(2, second))); 69 auto third = Period(Date(2009, 01, 17), Date(2009, 01, 22)); 70 assert(!first.overlapsWith(third)); 71 assertNotThrown!ExclusionConstraintException(bs.add(new B(2, third)));